package com.wzdigit.wms.raw.service.initialize;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.domain.basic.Sku;
import com.wzdigit.wms.basic.domain.basic.Warehouse;
import com.wzdigit.wms.basic.domain.inv.InvInitTemp;
import com.wzdigit.wms.basic.enums.AsnDtlStatusEnum;
import com.wzdigit.wms.basic.enums.AsnHeaderStatusEnum;
import com.wzdigit.wms.basic.enums.AsnTypeEnum;
import com.wzdigit.wms.basic.enums.QaStatusEnum;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.basic.mapper.core.basic.WarehouseMapper;
import com.wzdigit.wms.basic.mapper.core.inv.InvInitTempMapper;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.common.entity.ExcelExportConfig;
import com.wzdigit.wms.common.entity.StatusCode;
import com.wzdigit.wms.common.utils.HttpExcel;
import com.wzdigit.wms.raw.client.request.initialize.report.ImportInvTempRequest;
import com.wzdigit.wms.raw.client.request.initialize.report.InitializeSearchRequest;
import com.wzdigit.wms.raw.client.response.initialize.report.*;
import com.wzdigit.wms.raw.mapper.initialize.InitializeReportMapper;

import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 库存初始化BS  Service
 * Created by zyf on 2021/8/19 16:51
 */
@Service
public class InitializeReportService {

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    private InvInitTempMapper invInitTempMapper;

    @Autowired
    private InitializeReportMapper initializeReportMapper;

    @Value(value = "${default_owner.name}")
    private String DEFAULT_OWNER;

    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
    private BasicDataItemDetailApi dataItemDetailApi;


    /**
     * 分页查询主档信息
     *
     * @param search
     * @param pager
     * @param servletRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<InitializeSearchResponse>> searchMain(InitializeSearchRequest search, Pager<?> pager,
                                                                HttpServletRequest servletRequest) {
        Page<InitializeSearchResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        List<InitializeSearchResponse> datas = initializeReportMapper.searchAll(search);
        for (InitializeSearchResponse data : datas) {
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.enumName);
                }
            }
        }
        PagerInfo<List<InitializeSearchResponse>> pagerInfo = new PagerInfo<>();
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }


    /**
     * 获取当前用户对应ERP仓库
     * @param pager
     * @param servletRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<ErpCodeResponse>> erpCodePerm(String filter, Pager<?> pager, HttpServletRequest servletRequest) {
        Page<ErpCodeResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        List<ErpCodeResponse> list = initializeReportMapper.selectErpCode(filter);

        PagerInfo<List<ErpCodeResponse>> pagerInfo = new PagerInfo<>();
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(list);
        return pagerInfo;
    }

    //新增/修改查询下拉框信息
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<WhsQastatusResponse>> insertSearch(String erpCode, String factory, Pager<?> pager) {
        Page<WhsQastatusResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        List<WhsQastatusResponse> datas = initializeReportMapper.insertSearch(erpCode, factory);
        for (WhsQastatusResponse data : datas) {
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.enumName);
                }
            }
        }
        PagerInfo<List<WhsQastatusResponse>> pagerInfo = new PagerInfo<>();
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //新增
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result<?> insertInvTemp(InvInitTemp invInitTemp, HttpServletRequest servletRequest) {

        if (invInitTemp.getWhsErp()==null){
            Shift.fatal("ERP仓库不能为空!");
        }
        if (invInitTemp.getFactory()==null){
            Shift.fatal("工厂代码不能为空!");
        }
        if (invInitTemp.getWhs()==null){
            Shift.fatal("仓库不能为空！");
        }
        if (invInitTemp.getSkuCode() == null) {
            Shift.fatal("物料[" + invInitTemp.getSkuCode() + "]不存在!");
        }
        if (invInitTemp.getBookQty()==null){
            Shift.fatal("账面数量不能为空!");
        }
        if (invInitTemp.getBookQty().signum() <= 0) {
            Shift.fatal("账面数量需大于0!");
        }
        if (invInitTemp.getQaStatus()==null){
            Shift.fatal("品质状态不能为空!");
        }
        List<String> whsCodeList = initializeReportMapper.selectMappingWhs(invInitTemp.getWhsErp(), invInitTemp.getFactory(), invInitTemp.getQaStatus());
        if (CollectionUtil.isEmpty(whsCodeList)){
            Shift.fatal("请配置仓库映射数据!");
        }else if (whsCodeList.size()>1){
            Shift.fatal("存在重复的仓库映射数据!");
        }

        Warehouse mappingWarehouse = warehouseMapper.selectOne(new QueryWrapper<Warehouse>().eq("WHS_CODE", whsCodeList.get(0)));
        if (mappingWarehouse==null){
            Shift.fatal("请配置仓库信息");
        }else if (!new Integer(1).equals(mappingWarehouse.getWhsType())){
            Shift.fatal("仓库["+mappingWarehouse.getWhsCode()+"]非原材料仓库");
        }

        Warehouse insertWarehouse = warehouseMapper.selectOne(new QueryWrapper<Warehouse>().eq("WHS_ID", invInitTemp.getWhs()));

        if (!insertWarehouse.getWhsCode().equals(mappingWarehouse.getWhsCode())){
            Shift.fatal("仓库["+insertWarehouse.getWhsCode()+"]没有配置仓库映射!");
        }

        invInitTemp.setCreateUser(HttpSessionUtil.getLoginName(servletRequest));
        invInitTemp.setCreateTime(new Date());
        invInitTemp.setActQty(BigDecimal.ZERO);
        invInitTempMapper.insert(invInitTemp);
//		Shift.fatal("、、、、、、、、、、、、");
        return new Result<>();
    }


    //跳转查询页面
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public InvInitTemp searchInvTempById(BigDecimal invInitTempId,HttpServletRequest servletRequest){
        return invInitTempMapper.selectOne(new QueryWrapper<InvInitTemp>().eq("INV_INIT_ID", invInitTempId));
    }

    //修改
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result<?> updateInvTemp(BigDecimal invInitTempId,BigDecimal bookQty,BigDecimal actQty, HttpServletRequest servletRequest){
        if(bookQty.compareTo(actQty) == -1){
            Shift.fatal("账面数量不能小于实盘数量");
        }
        initializeReportMapper.updateBookQty(invInitTempId,bookQty,HttpSessionUtil.getLoginName(servletRequest),new Date());
        return new Result<>();
    }

    //导出
    @Transactional
    public void exportInitializeReport(
            InitializeSearchRequest search,
            HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception{
        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;
        try {
            List<InitializeSearchResponse> resultDatas = initializeReportMapper.searchAll(search);
            for (InitializeSearchResponse data : resultDatas) {
                if (data.getQaStatus()!=null){
                    QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                    if (qaStatusEnum !=null){
                        data.setQaStatusStr(qaStatusEnum.enumName);
                    }
                }
            }

            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("仓库", "whsCode", 120));
            configs.add(new ExcelExportConfig("ERP仓库", "erpCode", 120));
            configs.add(new ExcelExportConfig("工厂代码", "factory", 120));
            configs.add(new ExcelExportConfig("物料编码", "skuCode", 120));
            configs.add(new ExcelExportConfig("品质状态", "qaStatusStr", 120));
            configs.add(new ExcelExportConfig("账面数量", "bookQty", 120));
            configs.add(new ExcelExportConfig("实盘数量", "actQty", 120));
            configs.add(new ExcelExportConfig("创建时间", "createTime", 120));
            configs.add(new ExcelExportConfig("创建人", "createUser", 120));
            configs.add(new ExcelExportConfig("修改时间", "modifyTime", 120));
            configs.add(new ExcelExportConfig("修改人", "modifyUser", 120));

            workbook = HttpExcel.newListToExcel(resultDatas, configs);
            String userAgent = servletRequest.getHeader("USER-AGENT");
            String fileName = "库存初始化报表";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            servletResponse.setContentType("application/octet-stream");
            servletResponse.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            servletResponse.flushBuffer();
            out = servletResponse.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if(workbook != null) {
                workbook.close();
            }
        }

    }

    //导入
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ImportInvTempResponse importInvTemp(MultipartFile file,
                                               HttpServletRequest servletRequest,
                                               HttpServletResponse servletResponse){
        String loginName = HttpSessionUtil.getLoginName(servletRequest);
        List<ImportInvTempRequest> excel = null;
        try {
            InputStream inputStream = file.getInputStream();
            String[] properties = { "whsErp", "factory", "skuCode", "qaStatusStr",
                    "bookQtyStr", "comments"
            };
            excel = HttpExcel.importExcel(inputStream, ImportInvTempRequest.class, properties);
        } catch (Exception e) {
            // 模板错误，请确认
            e.printStackTrace();
            Shift.fatal(StatusCode.IMPORT_DATA_ERROR);
        }
        if (excel == null || excel.size() == 0) {
            // 该模板数据为空
            Shift.fatal(StatusCode.IMPORT_DATA_NULL);
        }

        // 失败、成功条数
        int fail = excel.size(), sucess = 0;
        // 失败记录集合
        List<ImportInvTempErrorResponse> errorList = new ArrayList<>();
        boolean flag;
        Date createDate=new Date();
        for (ImportInvTempRequest dto : excel) {
            ImportInvTempErrorResponse error=new ImportInvTempErrorResponse();
            flag = true;
            if (flag){
                if (dto.getWhsErp()==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行ERP仓库不能为空");
                    errorList.add(error);
                    flag = false;
                }
            }
            if (flag){
                if (dto.getFactory()==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行工厂代码不能为空");
                    errorList.add(error);
                    flag = false;
                }
            }
            if (flag){
                if (dto.getSkuCode()==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行物料代码不能为空");
                    errorList.add(error);
                    flag = false;
                }
            }
            if (flag){
                Sku sku = skuMapper.selectOne(new QueryWrapper<Sku>().eq("SKU_CODE", dto.getSkuCode()));
                if (sku==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行物料不存在");
                    errorList.add(error);
                    flag = false;
                }else {
                    dto.setSkuId(sku.getSkuId());
                }
            }
            if (flag){
                if (dto.getQaStatusStr()==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行品质状态不能为空");
                    errorList.add(error);
                    flag = false;
                }
            }
            if (flag){
                if (QaStatusEnum.WAIT.enumName.equals(dto.getQaStatusStr())){
                    dto.setQaStatus(QaStatusEnum.WAIT.code);
                }else if (QaStatusEnum.OK.enumName.equals(dto.getQaStatusStr())){
                    dto.setQaStatus(QaStatusEnum.OK.code);
                } else if (QaStatusEnum.NG.enumName.equals(dto.getQaStatusStr())){
                    dto.setQaStatus(QaStatusEnum.NG.code);
                }else {
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行品质状态应为:"+QaStatusEnum.WAIT.enumName+"/"
                            +QaStatusEnum.OK.enumName+"/"+QaStatusEnum.NG.enumName);
                    errorList.add(error);
                    flag = false;
                }
            }
            //仓库映射表查询仓库ID
            if (flag){
                List<String> whsCodeList = initializeReportMapper.selectMappingWhs(dto.getWhsErp(), dto.getFactory(), dto.getQaStatus());
                if (CollectionUtil.isEmpty(whsCodeList)){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行没有配置仓库映射表");
                    errorList.add(error);
                    flag = false;
                }else if (whsCodeList.size()>1){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行存在重复的仓库映射数据");
                    errorList.add(error);
                    flag = false;
                }else {
                    Warehouse warehouse = warehouseMapper.selectOne(new QueryWrapper<Warehouse>().eq("WHS_CODE", whsCodeList.get(0)));
                    if (warehouse==null){
                        setErrorMessage(error,dto);
                        error.setRowMessage("【第"+dto.getRow()+"】行没有配置WMS仓库信息");
                        errorList.add(error);
                        flag = false;
                    }else if (!new Integer(1).equals(warehouse.getWhsType())){
                        setErrorMessage(error,dto);
                        error.setRowMessage("【第"+dto.getRow()+"】行【"+warehouse.getWhsCode()+"】非原材料仓库");
                        errorList.add(error);
                        flag = false;
                    } else{
                        dto.setWhs(warehouse.getWhsId());
                    }
                }
            }
            if (flag){
                if (dto.getBookQtyStr()==null){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行账面数量不能为空");
                    errorList.add(error);
                    flag = false;
                }else if (!checkStrIsNum(dto.getBookQtyStr())){
                    setErrorMessage(error,dto);
                    error.setRowMessage("【第"+dto.getRow()+"】行账面数量必须为数字");
                    errorList.add(error);
                    flag = false;
                }else {
                    dto.setBookQty(new BigDecimal(dto.getBookQtyStr()));
                    dto.setActQty(BigDecimal.ZERO);
                    dto.setCreateUser(loginName);
                    dto.setCreateTime(createDate);
                }
            }
            if (flag){
                //新增数据
                initializeReportMapper.insertInvTemp(dto);
                fail--;
                sucess++;
                setErrorMessage(error,dto);
                errorList.add(error);
            }
        }
        ImportInvTempResponse result=new ImportInvTempResponse();
        result.setFailureCount(fail);
        result.setSucceessCount(sucess);
        result.setItems(errorList);
        return result;

    }

    private void setErrorMessage(ImportInvTempErrorResponse error,ImportInvTempRequest dto){
        error.setWhsErp(dto.getWhsErp());
        error.setWhs(dto.getWhs());
        error.setFactory(dto.getFactory());
        error.setSkuCode(dto.getSkuCode());
        error.setQaStatusStr(dto.getQaStatusStr());
        error.setBookQtyStr(dto.getBookQtyStr());
        error.setActQty(dto.getBookQty());
        error.setComments(dto.getComments());
    }

    //判断字符串是否为数字
    public static boolean isNumericzidai(String str) {
        Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]+");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    //判断字符串是否为数字
    public static boolean checkStrIsNum(String str) {
        String bigStr;
        try {
            bigStr = new BigDecimal(str).toString();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    //通过库存临时表id查询入库单主档
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<InitializeAsnHeader>> searchAsnHeader(String invInitTempId  ,Pager<?> pager){
        Page<String> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        List<InitializeAsnHeader> initializeAsnHeaders = initializeReportMapper.searchAsnHeader(invInitTempId);
        for (InitializeAsnHeader header : initializeAsnHeaders) {
            header.setOwner(DEFAULT_OWNER);
            if (header.getAsnStatus()!=null){
                AsnHeaderStatusEnum statusEnum = AsnHeaderStatusEnum.getEnumByCode(header.getAsnStatus());
                if (statusEnum!=null){
                    header.setAsnStatusStr(statusEnum.enumName);
                }
            }
            if (header.getAsnType()!=null){
                AsnTypeEnum typeEnum = AsnTypeEnum.getEnumByCode(header.getAsnType());
                if (typeEnum!=null){
                    header.setAsnTypeStr(typeEnum.enumName);
                }
            }
        }
        PagerInfo<List<InitializeAsnHeader>> pagerInfo = new PagerInfo<>();
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(initializeAsnHeaders);

        return pagerInfo;
    }

    //根据入库单主档查询明细
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<InitializeAsnDtl> searchAsnDtl(BigDecimal asnHeaderId){
        List<InitializeAsnDtl> dtlList = initializeReportMapper.searchAsnDtl(asnHeaderId);
        for (InitializeAsnDtl dtl : dtlList) {
            if (dtl.getDtlStatus()!=null){
                AsnDtlStatusEnum dtlStatusEnum = AsnDtlStatusEnum.getEnumByCode(dtl.getDtlStatus());
                if (dtlStatusEnum!=null){
                    dtl.setDtlStatusStr(dtlStatusEnum.enumName);
                }
            }
            if (dtl.getQaStatus()!=null){
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(dtl.getQaStatus());
                if (qaStatusEnum!=null){
                    dtl.setQaStatusStr(qaStatusEnum.enumName);
                }
            }
        }
        return dtlList;
    }
}
